home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #5 / Amiga Plus CD - 2000 - No. 5.iso / Tools / Dev / GameboyDev / GBDK / lib / font.ms < prev    next >
Text File  |  1999-03-29  |  11KB  |  715 lines

  1. ; font.ms
  2. ;
  3. ;    Michael Hope, 1999
  4. ;    michaelh@earthling.net
  5. ;    Distrubuted under the Artistic License - see www.opensource.org
  6. ;
  7.     .include        "global.s"
  8.     INCLUDE        "wait_hbl.mh"
  9.  
  10.     .globl    .cr_curs
  11.     .globl    .adv_curs
  12.     .globl    .cury, .curx
  13.     .globl    .display_off
  14.  
  15.     ; Structure offsets
  16.     sfont_handle_sizeof    =    3
  17.     sfont_handle_font    =    1
  18.     sfont_handle_first_tile    =    0
  19.  
  20.     ; Encoding types - lower 2 bits of font
  21.     FONT_256ENCODING    =    0
  22.     FONT_128ENCODING    =    1
  23.     FONT_NOENCODING        =    2
  24.  
  25.     ; Other bits
  26.     FONT_BCOMPRESSED    =    2
  27.     
  28.     .CR             =     0x0A          ; Unix
  29.     .SPACE            =    0x00
  30.  
  31.     ; Maximum number of fonts
  32.     .MAX_FONTS        =     6
  33.  
  34.     .area    _HEADER (ABS)
  35.  
  36.     .org    .MODE_TABLE+4*.T_MODE
  37.     JP    .tmode
  38.  
  39.     .module font.ms
  40.  
  41.     ; Globals from drawing.s
  42.     ; FIXME: Hmmm... check the linkage of these
  43.     .globl    .fg_colour
  44.     .globl    .bg_colour
  45.  
  46.     .area    _BSS
  47.     ; The current font
  48. font_current::
  49.     .ds    sfont_handle_sizeof
  50.     ; Cached copy of the first free tile
  51. font_first_free_tile::
  52.     .ds    1
  53.     ; Table containing descriptors for all of the fonts
  54. font_table::
  55.     .ds    sfont_handle_sizeof*.MAX_FONTS
  56.     
  57.     .area   _CODE
  58.  
  59.     ; Copy uncompressed 16 byte tiles from (BC) to (HL), length = DE*2
  60.     ; Note: HL must be aligned on a UWORD boundry
  61. font_copy_uncompressed::
  62.     ld    a,d
  63.     or    e
  64.     ret    z
  65.  
  66.     ld    a,h
  67.     cp    #0x98
  68.     jr    c,4$
  69.     sub    #0x98-0x88
  70.     ld    h,a
  71. 4$:
  72.     xor    a
  73.     cp    e        ; Special for when e=0 you will get another loop
  74.     jr    nz,1$
  75.     dec    d
  76. 1$:
  77.     WAIT_HBL
  78.     ld    a,(bc)
  79.     ld    (hl+),a
  80.     inc    bc
  81.     
  82.     WAIT_HBL
  83.     ld    a,(bc)
  84.     ld    (hl),a
  85.     inc    bc
  86.  
  87.     inc    l
  88.     jr    nz,2$
  89.     inc    h
  90.     ld    a,h        ; Special wrap-around
  91.     cp    #0x98
  92.     jr    nz,2$
  93.     ld    h,#0x88
  94. 2$:
  95.     dec    e
  96.     jr    nz,1$
  97.     dec    d
  98.     bit    7,d        ; -1?
  99.     jr    z,1$
  100.     ret
  101.  
  102.     ; Copy a set of compressed (8 bytes/cell) tiles to VRAM
  103.     ; Sets the foreground and background colours based on the current
  104.     ; font colours
  105.     ; Entry:
  106.     ;    From (BC) to (HL), length (DE) where DE = #cells * 8
  107.     ;    Uses the current fg_colour and bg_colour fields
  108. font_copy_compressed::
  109.     ld    a,d
  110.     or    e
  111.     ret    z        ; Do nothing
  112.  
  113.     ld    a,h
  114.     cp    #0x98        ; Take care of the 97FF -> 8800 wrap around
  115.     jr    c,font_copy_compressed_loop
  116.     sub    #0x98-0x88
  117.     ld    h,a
  118. font_copy_compressed_loop:
  119.     push    de
  120.     ld    a,(bc)
  121.     ld    e,a
  122.     inc    bc
  123.     push    bc
  124.  
  125.     ld    bc,#0
  126.                 ; Do the background colour first
  127.     ld    a,(.bg_colour)
  128.     bit    0,a
  129.     jr    z,font_copy_compressed_bg_grey1
  130.     ld    b,#0xFF
  131. font_copy_compressed_bg_grey1:
  132.     bit    1,a
  133.     jr    z,font_copy_compressed_bg_grey2
  134.     ld    c,#0xFF
  135. font_copy_compressed_bg_grey2:
  136.     ; BC contains the background colour
  137.     ; Compute what xoring we need to do to get the correct fg colour
  138.     ld    d,a
  139.     ld    a,(.fg_colour)
  140.     xor    d
  141.     ld    d,a
  142.  
  143.     bit    0,d
  144.     jr    z,font_copy_compressed_grey1
  145.     ld    a,e
  146.     xor    b
  147.     ld    b,a
  148. font_copy_compressed_grey1:
  149.     bit    1,d
  150.     jr    z,font_copy_compressed_grey2
  151.     ld    a,e
  152.     xor    c
  153.     ld    c,a
  154. font_copy_compressed_grey2:
  155.     WAIT_HBL
  156.     ld    (hl),b
  157.     inc    hl
  158.     WAIT_HBL
  159.     ld    (hl),c
  160.     inc    hl
  161.     ld    a,h        ; Take care of the 97FFF -> 8800 wrap around
  162.     cp    #0x98
  163.     jr    nz,1$
  164.     ld    h,#0x88
  165. 1$:
  166.     pop    bc
  167.     pop    de
  168.     dec    de
  169.     ld    a,d
  170.     or    e
  171.     jr    nz,font_copy_compressed_loop
  172.     ret
  173.     
  174. ; Load the font HL
  175. font_load::
  176.     call    .display_off
  177.     push    hl
  178.  
  179.     ; Find the first free font entry
  180.     ld    hl,#font_table+sfont_handle_font
  181.     ld    b,#.MAX_FONTS
  182. font_load_find_slot:
  183.     ld    a,(hl)        ; Check to see if this entry is free
  184.     inc    hl        ; Free is 0000 for the font pointer
  185.     or    (hl)
  186.     cp    #0
  187.     jr    z,font_load_found
  188.  
  189.     inc    hl
  190.     inc    hl
  191.     dec    b
  192.     jr    nz,font_load_find_slot
  193.     pop    hl
  194.     ld    hl,#0
  195.     jr    font_load_exit    ; Couldn't find a free space
  196. font_load_found:
  197.                 ; HL points to the end of the free font table entry
  198.     pop    de
  199.     ld    (hl),d        ; Copy across the font struct pointer
  200.     dec    hl
  201.     ld    (hl),e
  202.  
  203.     ld    a,(font_first_free_tile)
  204.     dec    hl
  205.     ld    (hl),a        
  206.  
  207.     push    hl
  208.     call    font_set    ; Set this new font to be the default
  209.     
  210.     ; Only copy the tiles in if were in text mode
  211.     ld    a,(.mode)
  212.     and    #.T_MODE
  213.     
  214.     call    nz,font_copy_current
  215.  
  216.                 ; Increase the 'first free tile' counter
  217.     ld    hl,#font_current+sfont_handle_font
  218.     ld    a,(hl+)
  219.     ld    h,(hl)
  220.     ld    l,a
  221.  
  222.     inc    hl        ; Number of tiles used
  223.     ld    a,(font_first_free_tile)
  224.     add    a,(hl)
  225.     ld    (font_first_free_tile),a
  226.  
  227.     pop    hl        ; Return font setup in HL
  228. font_load_exit:
  229.     ;; Turn the screen on
  230.     LDH     A,(.LCDC)
  231.     OR      #0b10000001     ; LCD           = On
  232.                 ; BG            = On
  233.     AND     #0b11100111     ; BG Chr        = 0x8800
  234.                 ; BG Bank       = 0x9800
  235.     LDH     (.LCDC),A
  236.  
  237.     RET
  238.  
  239.     ; Copy the tiles from the current font into VRAM
  240. font_copy_current::    
  241.                 ; Find the current font data
  242.     ld    hl,#font_current+sfont_handle_font
  243.     ld    a,(hl+)
  244.     ld    h,(hl)
  245.     ld    l,a
  246.  
  247.     inc    hl        ; Points to the 'tiles required' entry
  248.     ld    e,(hl)
  249.     ld    d,#0
  250.     rl    e        ; Multiple DE by 8
  251.     rl    d
  252.     rl    e
  253.     rl    d
  254.     rl    e
  255.     rl    d        ; DE has the length of the tile data
  256.     dec    hl
  257.  
  258.     ld    a,(hl)        ; Get the flags
  259.     push    af        
  260.     and    #3            ; Only lower 2 bits set encoding table size
  261.  
  262.     ld    bc,#128
  263.     cp    #FONT_128ENCODING    ; 0 for 256 char encoding table, 1 for 128 char
  264.     jr    z,font_copy_current_copy
  265.  
  266.     ld    bc,#0
  267.     cp    #FONT_NOENCODING
  268.     jr    z,font_copy_current_copy
  269.  
  270.     ld    bc,#256            ; Must be 256 element encoding
  271. font_copy_current_copy:
  272.     inc    hl
  273.     inc    hl        ; Points to the start of the encoding table
  274.     add    hl,bc        
  275.     ld    c,l
  276.     ld    b,h        ; BC points to the start of the tile data        
  277.  
  278.     ; Find the offset in VRAM for this font
  279.     ld    a,(font_current+sfont_handle_first_tile)    ; First tile used for this font
  280.     ld    l,a        
  281.     ld    h,#0
  282.     add    hl,hl
  283.     add    hl,hl
  284.     add    hl,hl
  285.     add    hl,hl
  286.  
  287.     ld    a,#0x90        ; Tile 0 is at 9000h
  288.     add    a,h
  289.     ld    h,a
  290.                 ; Is this font compressed?
  291.     pop    af        ; Recover flags
  292.     bit    FONT_BCOMPRESSED,a
  293.                 ; Do the jump in a mildly different way
  294.     jp    z,font_copy_uncompressed
  295.     jp    font_copy_compressed
  296.  
  297.     ; Set the current font to HL
  298. font_set::
  299.     ld    a,(hl+)
  300.     ld    (font_current),a
  301.     ld    a,(hl+)
  302.     ld    (font_current+1),a
  303.     ld    a,(hl+)
  304.     ld    (font_current+2),a
  305.     ret
  306.     
  307.     ;; Print a character with interpretation
  308. .put_char::
  309.     ; See if it's a special char
  310.     cp    #.CR
  311.     jr    nz,1$
  312.  
  313.     ; Now see if were checking special chars
  314.     push    af
  315.     ld    a,(.mode)
  316.     and    #.M_NO_INTERP
  317.     jr    nz,2$
  318.     call    .cr_curs
  319.     pop    af
  320.     ret
  321. 2$:
  322.     pop    af
  323. 1$:
  324.     CALL    .set_char
  325.     CALL    .adv_curs
  326.     RET
  327.  
  328.     ;; Print a character without interpretation
  329. .out_char::
  330.     CALL    .set_char
  331.     CALL    .adv_curs
  332.     RET
  333.  
  334.     ;; Delete a character
  335. .del_char::
  336.     CALL    .rew_curs
  337.     LD    A,#.SPACE
  338.     CALL    .set_char
  339.     RET
  340.  
  341.     ;; Print the character in A
  342. .set_char:
  343.     push    af
  344.     ld    a,(font_current+2)
  345.     ; Must be non-zero if the font system is setup (cant have a font in page zero)
  346.     or    a
  347.     jr    nz,3$
  348.  
  349.     ; Font system is not yet setup - init it and copy in the ibm font
  350.     ; Kind of a compatibility mode
  351.     call    _font_init
  352.     
  353.     ; Need all of the tiles
  354.     xor    a
  355.     ld    (font_first_free_tile),a
  356.  
  357.     .globl    _font_ibm_fixed
  358.     ld    hl,#_font_ibm_fixed
  359.     call    font_load
  360. 3$:
  361.     pop    af
  362.     push    bc
  363.     push    de
  364.     push    hl
  365.                 ; Compute which tile maps to this character
  366.     ld    e,a
  367.     ld    hl,#font_current+sfont_handle_font
  368.     ld    a,(hl+)
  369.     ld    h,(hl)
  370.     ld    l,a
  371.     ld    a,(hl+)
  372.     and    #3
  373.     cp    #FONT_NOENCODING
  374.     jr    z,set_char_no_encoding
  375.     inc    hl
  376.                 ; Now at the base of the encoding table
  377.                 ; E is set above
  378.     ld    d,#0
  379.     add    hl,de
  380.     ld    e,(hl)        ; That's the tile!
  381. set_char_no_encoding:
  382.     ld    a,(font_current+0)
  383.     add    a,e
  384.     ld    e,a
  385.  
  386.     LD      A,(.cury)       ; Y coordinate
  387.     LD      L,A
  388.     LD      H,#0x00
  389.     ADD     HL,HL
  390.     ADD     HL,HL
  391.     ADD     HL,HL
  392.     ADD     HL,HL
  393.     ADD     HL,HL
  394.     LD      A,(.curx)       ; X coordinate
  395.     LD      C,A
  396.     LD      B,#0x00
  397.     ADD     HL,BC
  398.     LD      BC,#0x9800
  399.     ADD     HL,BC
  400.  
  401.     WAIT_HBL
  402.     LD      (HL),E
  403.     POP     HL
  404.     POP     DE
  405.     POP     BC
  406.     RET
  407.  
  408. _putchar::
  409.     LDA     HL,2(SP)        ; Skip return address
  410.     LD      A,(HL)          ; A = c
  411.     CALL    .put_char
  412.     RET
  413.  
  414. _setchar::
  415.     push    bc
  416.     LDA     HL,4(SP)        ; Skip return address
  417.     LD      A,(HL)          ; A = c
  418.     CALL    .set_char
  419.     pop    bc
  420.     RET
  421.  
  422. _font_load::
  423.     push    bc
  424.     LDA     HL,4(SP)        ; Skip return address and bc
  425.     LD      A,(HL)          ; A = c
  426.     inc    hl
  427.     ld    h,(hl)
  428.     ld    l,a
  429.     call    font_load
  430.     push    hl
  431.     pop    de        ; Return in DE
  432.     pop    bc
  433.     RET
  434.  
  435. _font_set::
  436.     push    bc
  437.     LDA     HL,4(SP)        ; Skip return address
  438.     LD      A,(HL)          ; A = c
  439.     inc    hl
  440.     ld    h,(hl)
  441.     ld    l,a
  442.     call    font_set
  443.     pop    bc
  444.     ld    de,#0        ; Always good...
  445.     RET
  446.  
  447. _font_init::
  448.     push    bc
  449.     .globl    .tmode
  450.  
  451.     call    .tmode
  452.  
  453.     ld    a,#1        ; We use the first tile as a space _always_
  454.     ld    (font_first_free_tile),a
  455.  
  456.     ; Clear the font table
  457.     xor    a
  458.     ld    hl,#font_table
  459.     ld    b,#sfont_handle_sizeof*.MAX_FONTS
  460. 1$:
  461.     ld    (hl+),a
  462.     dec    b
  463.     jr    nz,1$
  464.     ld    a,#3
  465.     ld    (.fg_colour),a
  466.     ld    a,#0
  467.     ld    (.bg_colour),a
  468.  
  469.     call    .cls
  470.     pop    bc
  471.     ret
  472.     
  473. _print_repeat::
  474.     push    bc
  475.     lda    hl,4(sp)
  476.     ld    e,(hl)
  477.     inc    hl
  478.     ld    d,(hl)
  479.     xor    a
  480.     cp    d
  481.     jr    nz,_print_repeat_go
  482.     pop    bc
  483.     ret
  484. _print_repeat_go:
  485.     ld    a,e
  486.     push    de
  487.     call    .put_char
  488.     pop    de
  489.     dec    d
  490.     jr    nz,_print_repeat_go
  491.     pop    bc
  492.     ret
  493.  
  494. _gotoxy::
  495.     lda    hl,2(sp)
  496.     ld    a,(hl+)
  497.     ld    (.curx),a
  498.     ld    a,(hl)
  499.     ld    (.cury),a
  500.     ret
  501.  
  502. _cls::
  503. .cls::    
  504.     PUSH    DE
  505.     PUSH    HL
  506.     LD    HL,#0x9800
  507.     LD    E,#0x20        ; E = height
  508. 1$:
  509.     LD    D,#0x20        ; D = width
  510. 2$:
  511.     WAIT_HBL
  512.  
  513.     LD    (HL),#.SPACE    ; Always clear
  514.     INC    HL
  515.     DEC    D
  516.     JR    NZ,2$
  517.     DEC    E
  518.     JR    NZ,1$
  519.     POP    HL
  520.     POP    DE
  521.     RET
  522.  
  523.     ; Support routines
  524. _posx::
  525.     LD    A,(.mode)
  526.     AND    #.T_MODE
  527.     JR    NZ,1$
  528.     PUSH    BC
  529.     CALL    .tmode
  530.     POP    BC
  531. 1$:
  532.     LD    A,(.curx)
  533.     LD    E,A
  534.     RET
  535.  
  536. _posy::
  537.     LD    A,(.mode)
  538.     AND    #.T_MODE
  539.     JR    NZ,1$
  540.     PUSH    BC
  541.     CALL    .tmode
  542.     POP    BC
  543. 1$:
  544.     LD    A,(.cury)
  545.     LD    E,A
  546.     RET
  547.  
  548.     ;; Rewind the cursor
  549. .rew_curs:
  550.     PUSH    HL
  551.     LD    HL,#.curx    ; X coordinate
  552.     XOR    A
  553.     CP    (HL)
  554.     JR    Z,1$
  555.     DEC    (HL)
  556.     JR    99$
  557. 1$:
  558.     LD    (HL),#.MAXCURSPOSX
  559.     LD    HL,#.cury    ; Y coordinate
  560.     XOR    A
  561.     CP    (HL)
  562.     JR    Z,99$
  563.     DEC    (HL)
  564. 99$:
  565.     POP    HL
  566.     RET
  567.  
  568. .cr_curs::
  569.     PUSH    HL
  570.     XOR    A
  571.     LD    (.curx),A
  572.     LD    HL,#.cury    ; Y coordinate
  573.     LD    A,#.MAXCURSPOSY
  574.     CP    (HL)
  575.     JR    Z,2$
  576.     INC    (HL)
  577.     JR    99$
  578. 2$:
  579.     CALL    .scroll
  580. 99$:
  581.     POP    HL
  582.     RET
  583.  
  584. .adv_curs::
  585.     PUSH    HL
  586.     LD    HL,#.curx    ; X coordinate
  587.     LD    A,#.MAXCURSPOSX
  588.     CP    (HL)
  589.     JR    Z,1$
  590.     INC    (HL)
  591.     JR    99$
  592. 1$:
  593.     LD    (HL),#0x00
  594.     LD    HL,#.cury    ; Y coordinate
  595.     LD    A,#.MAXCURSPOSY
  596.     CP    (HL)
  597.     JR    Z,2$
  598.     INC    (HL)
  599.     JR    99$
  600. 2$:
  601.     ;; See if scrolling is disabled
  602.     LD    A,(.mode)
  603.     AND    #.M_NO_SCROLL
  604.     JR    Z,3$
  605.     ;; Nope - reset the cursor to (0,0)
  606.     XOR    A
  607.     LD    (.cury),A
  608.     LD    (.curx),A
  609.     JR    99$
  610. 3$:    
  611.     CALL    .scroll
  612. 99$:
  613.     POP    HL
  614.     RET
  615.  
  616.     ;; Scroll the whole screen
  617. .scroll:
  618.     PUSH    BC
  619.     PUSH    DE
  620.     PUSH    HL
  621.     LD    HL,#0x9800
  622.     LD    BC,#0x9800+0x20 ; BC = next line
  623.     LD    E,#0x20-0x01    ; E = height - 1
  624. 1$:
  625.     LD    D,#0x20        ; D = width
  626. 2$:
  627.     LDH    A,(.STAT)
  628.     AND    #0x02
  629.     JR    NZ,2$
  630.  
  631.     LD    A,(BC)
  632.     LD    (HL+),A
  633.     INC    BC
  634.     DEC    D
  635.     JR    NZ,2$
  636.     DEC    E
  637.     JR    NZ,1$
  638.  
  639.     LD    D,#0x20
  640. 3$:
  641.     LDH    A,(.STAT)
  642.     AND    #0x02
  643.     JR    NZ,3$
  644.  
  645.     LD    A,#.SPACE
  646.     LD    (HL+),A
  647.     DEC    D
  648.     JR    NZ,3$
  649.     POP    HL
  650.     POP    DE
  651.     POP    BC
  652.     RET
  653.  
  654.     .area    _BSS
  655. .curx::                ; Cursor position
  656.     .ds    0x01
  657. .cury::
  658.     .ds    0x01
  659.     .area    _CODE
  660.  
  661.     .globl    .vbl
  662.     .globl    .lcd
  663.     .globl    .int_0x40
  664.     .globl    .int_0x48
  665.     .globl    .remove_int
  666.  
  667.     ;; Enter text mode
  668. .tmode::
  669.     DI            ; Disable interrupts
  670.  
  671.     ;; Turn the screen off
  672.     LDH    A,(.LCDC)
  673.     BIT    7,A
  674.     JR    Z,1$
  675.  
  676.     ;; Turn the screen off
  677.     CALL    .display_off
  678.  
  679.     ;; Remove any interrupts setup by the drawing routine
  680.     LD    BC,#.vbl
  681.     LD    HL,#.int_0x40
  682.     CALL    .remove_int
  683.     LD    BC,#.lcd
  684.     LD    HL,#.int_0x48
  685.     CALL    .remove_int
  686. 1$:
  687.  
  688.     CALL    .tmode_out
  689.  
  690.     ;; Turn the screen on
  691.     LDH    A,(.LCDC)
  692.     OR    #0b10000001    ; LCD        = On
  693.                 ; BG        = On
  694.     AND    #0b11100111    ; BG Chr    = 0x8800
  695.                 ; BG Bank    = 0x9800
  696.     LDH    (.LCDC),A
  697.  
  698.     EI            ; Enable interrupts
  699.  
  700.     RET
  701.  
  702.     ;; Text mode (out only)
  703. .tmode_out::
  704.     XOR    A
  705.     LD    (.curx),A
  706.     LD    (.cury),A
  707.  
  708.     ;; Clear screen
  709.     CALL    .cls
  710.  
  711.     LD    A,#.T_MODE
  712.     LD    (.mode),A
  713.  
  714.     RET
  715.